package com.mini.es.service;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.mini.es.model.EsBusinessStudentBigLessonXcx;
import com.mini.es.model.EsBusinessStudentOrderInfo;
import com.mini.es.repository.EsBusinessStudentBigLessonXcxRepository;
import com.mini.mysql.model.BusinessStudentBigLessonXcx;
import com.mini.mysql.model.BusinessTeacherInfo;
import com.mini.mysql.service.BusinessTeacherInfoService;
import com.mini.mysql.service.MnsService;
import com.mini.util.CalendarUtil;
import com.mini.vo.BigLessonOrderCondition;
import com.mini.vo.KanbanDataFormatVO;
import com.mini.vo.KanbanPageCondition;
import com.mini.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.common.StopWatch;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.mini.es.model.EsBusinessStudentBigLessonXcx.Fields.bigLessUpdateTime;
import static com.mini.es.service.EsBusinessStudentOrderInfoServiceImpl.getFloatValue;
import static com.mini.es.service.EsBusinessStudentOrderInfoServiceImpl.getIntegerValue;
import static org.elasticsearch.search.aggregations.AggregationBuilders.count;
import static org.elasticsearch.search.aggregations.AggregationBuilders.sum;

/**
 * @author anjl
 * @date 2021/3/17
 **/
@Slf4j
@Service
public class EsBusinessStudentBigLessonXcxServiceImpl implements EsBusinessStudentBigLessonXcxService {

    @Autowired
    private MnsService mnsService;
    @Autowired
    private BusinessTeacherInfoService businessTeacherInfoService;

    @Override
    public Iterable<EsBusinessStudentBigLessonXcx> save(List<EsBusinessStudentBigLessonXcx> list) {
        if (Objects.isNull(list) || list.isEmpty()) {
            return null;
        }
        Date now = new Date();
        list.forEach(info -> info.setUpdateTime(now));
        return esBusinessStudentBigLessonXcxRepository.saveAll(list);
    }

    @Override
    public EsBusinessStudentBigLessonXcx findLatestUpdateTimeData() {
        Pageable pageable = PageRequest.of(1, 1, Sort.Direction.DESC, bigLessUpdateTime);
        try {
            Page<EsBusinessStudentBigLessonXcx> page = esBusinessStudentBigLessonXcxRepository.findAll(pageable);
            return page.getContent().isEmpty() ? null : page.getContent().get(0);
        } catch (SearchPhaseExecutionException e) {
            log.error("", e);
        }
        return null;
    }

    @Override
    public EsBusinessStudentBigLessonXcx findLatestMysqlUpdateTimeData() {
        Pageable pageable = PageRequest.of(1, 1, Sort.Direction.DESC, EsBusinessStudentBigLessonXcx.Fields.mysqlUpdateTime);
        Page<EsBusinessStudentBigLessonXcx> page = esBusinessStudentBigLessonXcxRepository.findAll(pageable);
        return page.getContent().isEmpty() ? null : page.getContent().get(0);
    }

    @Override
    public EsBusinessStudentBigLessonXcx findLatestSecondOrderUpdateTimeData() {
        Pageable pageable = PageRequest.of(1, 1, Sort.Direction.DESC, EsBusinessStudentBigLessonXcx.Fields.secondOrderUpdateTime);
        Page<EsBusinessStudentBigLessonXcx> page = esBusinessStudentBigLessonXcxRepository.findAll(pageable);
        return page.getContent().isEmpty() ? null : page.getContent().get(0);
    }

    @Override
    public EsBusinessStudentBigLessonXcx findLatestDeptUpdateTimeData() {
        Pageable pageable = PageRequest.of(1, 1, Sort.Direction.DESC, EsBusinessStudentBigLessonXcx.Fields.deptUpdateTime);
        Page<EsBusinessStudentBigLessonXcx> page = esBusinessStudentBigLessonXcxRepository.findAll(pageable);
        return page.getContent().isEmpty() ? null : page.getContent().get(0);
    }

    @Override
    public Page<EsBusinessStudentBigLessonXcx> pageBySecondOrderId(Long secondOrderId, Date secondOrderUpdateTime, Pageable pageable) {
        BoolQueryBuilder qb = QueryBuilders.boolQuery();
        qb.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.secondOrderId, secondOrderId));
        qb.mustNot(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.secondOrderUpdateTime, secondOrderUpdateTime.getTime()));
        return esBusinessStudentBigLessonXcxRepository.search(qb, pageable);
    }

    @Override
    public Page<EsBusinessStudentBigLessonXcx> pageByMiniTeacherId(Long miniTeacherId, Date deptUpdateTime, Pageable pageable) {
        BoolQueryBuilder qb = QueryBuilders.boolQuery();
        qb.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.miniTeacherId, miniTeacherId));
        qb.mustNot(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.deptUpdateTime, deptUpdateTime.getTime()));
        return esBusinessStudentBigLessonXcxRepository.search(qb, pageable);
    }

    @Override
    public Page<EsBusinessStudentBigLessonXcx> pageBySecondTeacherId(Long secondTeacherId, Date deptUpdateTime, Pageable pageable) {
        BoolQueryBuilder qb = QueryBuilders.boolQuery();
        qb.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.secondTeacherId, secondTeacherId));
        qb.mustNot(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.deptUpdateTime, deptUpdateTime.getTime()));
        return esBusinessStudentBigLessonXcxRepository.search(qb, pageable);
    }

    @Override
    public Page<EsBusinessStudentBigLessonXcx> pageBySku(Long sku, Pageable pageable) {
        BoolQueryBuilder qb = QueryBuilders.boolQuery();
        qb.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.sku, sku + ""));
        return esBusinessStudentBigLessonXcxRepository.search(qb, pageable);
    }

    @Override
    public List<EsBusinessStudentBigLessonXcx> findAllById(List<String> ids) {
        ArrayList<EsBusinessStudentBigLessonXcx> list = Lists.newArrayList();
        esBusinessStudentBigLessonXcxRepository.findAllById(ids).forEach(list::add);
        return list;
    }

    @Override
    public List<EsBusinessStudentBigLessonXcx> findByMiniOrderNoIn(List<String> miniOrderNoList) {
        return esBusinessStudentBigLessonXcxRepository.findByMiniOrderNoIn(miniOrderNoList);
    }

    @Override
    public List<EsBusinessStudentBigLessonXcx> findDeposit(Set<String> relatedKeySet, String orderState, Integer orderDepositType) {
        BoolQueryBuilder qb = QueryBuilders.boolQuery();

        BoolQueryBuilder relateKeyOr = QueryBuilders.boolQuery();
        relatedKeySet.forEach(s -> {
            relateKeyOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.relatedKey, s));
        });
        qb.must(relateKeyOr);
        qb.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.orderState, BusinessStudentBigLessonXcx.OrderState.PAY_FINISH.getState()));
        qb.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.orderDepositType, BusinessStudentBigLessonXcx.OrderDeposiType.ORDER_PDEPOSIT.getType().intValue()));

        ArrayList<EsBusinessStudentBigLessonXcx> list = Lists.newArrayList();
        esBusinessStudentBigLessonXcxRepository.search(qb).forEach(list::add);

        return list;
    }

    @Override
    public Page<EsBusinessStudentBigLessonXcx> pageByCondition(BigLessonOrderCondition condition) {
        BoolQueryBuilder qb = QueryBuilders.boolQuery();
        ArrayList<EsBusinessStudentBigLessonXcx> list = Lists.newArrayList();
//        List<String> orderStateList = new ArrayList<>();
//        orderStateList.add("15");
//        orderStateList.add("25");
//        qb.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.orderState, toStringArray(orderStateList)));
        //以下是主表查询

        BoolQueryBuilder state15 = QueryBuilders.boolQuery();
        state15.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.orderState, "15"));
        state15.must(QueryBuilders.rangeQuery(EsBusinessStudentBigLessonXcx.Fields.payAmount).gt(0));

        BoolQueryBuilder state40 = QueryBuilders.boolQuery();
        state40.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.orderState, "40"));
        state40.must(QueryBuilders.rangeQuery(EsBusinessStudentBigLessonXcx.Fields.payAmount).gt(0));

        BoolQueryBuilder stateOr = QueryBuilders.boolQuery();
        stateOr.should(state15);
        stateOr.should(state40);
//        QueryBuilders.boolQuery().must(QueryBuilders.existsQuery(EsBusinessStudentBigLessonXcx.Fields.changeClassStatus))
        stateOr.should(QueryBuilders.existsQuery(EsBusinessStudentBigLessonXcx.Fields.changeClassStatus));
        qb.must(stateOr);
        if (StringUtils.isNotEmpty(condition.getDateStart())) {
            qb.must(QueryBuilders.rangeQuery(EsBusinessStudentBigLessonXcx.Fields.payFinishTime).gte(CalendarUtil.parseDefaultDate(condition.getDateStart()).getTime()));
        }
        if (StringUtils.isNotEmpty(condition.getDateEnd())) {
            qb.must(QueryBuilders.rangeQuery(EsBusinessStudentBigLessonXcx.Fields.payFinishTime).lte(CalendarUtil.parseDefaultDate(condition.getDateEnd()).getTime()));
        }
        if (Objects.nonNull(condition.getOrderSourceType())) {
            qb.must(QueryBuilders.termQuery(EsBusinessStudentBigLessonXcx.Fields.orderSourceType, condition.getOrderSourceType()));
        }
        if (Objects.nonNull(condition.getAscriptionCode())) {
            qb.must(QueryBuilders.termQuery(EsBusinessStudentBigLessonXcx.Fields.operationStage, condition.getAscriptionCode()));
        }
        //chanceStates和continueType，对应mysql中secondOrder表字段
        if ((Objects.nonNull(condition.getChanceStates()))) {
            if (condition.getChanceStates() == 0 || condition.getChanceStates() == 1) {
                qb.must(QueryBuilders.termQuery(EsBusinessStudentBigLessonXcx.Fields.chanceStates, condition.getChanceStates()));
            } else if (condition.getChanceStates() == 2) {
                BoolQueryBuilder queryOr = QueryBuilders.boolQuery();
                queryOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.chanceStates, 2));
                queryOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.chanceStates, 3));
                queryOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.operationStage, 0));
                qb.must(queryOr);
            }
        }
        if (Objects.nonNull(condition.getContinueType())) {
            qb.must(QueryBuilders.termQuery(EsBusinessStudentBigLessonXcx.Fields.continueType, condition.getContinueType()));
        }
        //对应student_info表
        if (Objects.nonNull(condition.getFzId())) {
            qb.must(QueryBuilders.termQuery(EsBusinessStudentBigLessonXcx.Fields.fzId, condition.getFzId()));
        }
        if (Objects.nonNull(condition.getWorkRoomId())) {
            qb.must(QueryBuilders.termQuery(EsBusinessStudentBigLessonXcx.Fields.workRoomId, condition.getWorkRoomId()));
        }
        if (StringUtils.isNotEmpty(condition.getChannelCode())) {
            qb.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.channelCode, condition.getChannelCode()));
        }
        if(StringUtils.isNotEmpty(condition.getChangeClassStatus())){
            qb.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.changeClassStatus, condition.getChangeClassStatus()));
        }
        if(StringUtils.isNotEmpty(condition.getOrderState())){
            qb.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.orderState, condition.getOrderState()));
        }
        if (StringUtils.isNotEmpty(condition.getKeyword())) {
            BoolQueryBuilder xcxOr = QueryBuilders.boolQuery();
            xcxOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.orderNo, condition.getKeyword()));
            xcxOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.phoneNumber, condition.getPhoneNo()));
            xcxOr.should(QueryBuilders.wildcardQuery(EsBusinessStudentBigLessonXcx.Fields.username, "*" + condition.getKeyword() + "*"));
            xcxOr.should(QueryBuilders.wildcardQuery(EsBusinessStudentBigLessonXcx.Fields.operateRemark, "*" + condition.getKeyword() + "*"));

            xcxOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.miniOrderNo, condition.getKeyword()));
            xcxOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.phoneNo, condition.getPhoneNo()));
            xcxOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.wxId, condition.getKeyword()));
            xcxOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.userId, condition.getKeyword()));
            xcxOr.should(QueryBuilders.wildcardQuery(EsBusinessStudentBigLessonXcx.Fields.nickName, "*" + condition.getKeyword() + "*"));
            xcxOr.should(QueryBuilders.wildcardQuery(EsBusinessStudentBigLessonXcx.Fields.wechatName, "*" + condition.getKeyword() + "*"));
            xcxOr.should(QueryBuilders.wildcardQuery(EsBusinessStudentBigLessonXcx.Fields.wechatNameNote, "*" + condition.getKeyword() + "*"));
            qb.must(xcxOr);
        }
        if (Objects.nonNull(condition.getYunying())) {
            BoolQueryBuilder yunyingOr = QueryBuilders.boolQuery();
            yunyingOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.teacherId, condition.getYunying()));
            yunyingOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.miniTeacherId, condition.getYunying()));
            yunyingOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.secondTeacherId, condition.getYunying()));
            qb.must(yunyingOr);
        }
        if (Objects.nonNull(condition.getTeacherId())) {
            BoolQueryBuilder teacherOr = QueryBuilders.boolQuery();
            teacherOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.teacherId, condition.getTeacherId()));
            teacherOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.miniTeacherId, condition.getTeacherId()));
            teacherOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.secondTeacherId, condition.getTeacherId()));
            qb.must(teacherOr);
        }
        if (StringUtils.isNotEmpty(condition.getLevel()) && Objects.nonNull(condition.getOrgId())) {
            if (condition.getLevel().equals("3")) {
                BoolQueryBuilder or = QueryBuilders.boolQuery();
                or.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.u1DeptLevel3Id, condition.getOrgId()));

                BoolQueryBuilder stageAnd = QueryBuilders.boolQuery();
                stageAnd.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.operationStage, 2));
                stageAnd.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.u2DeptLevel3Id, condition.getOrgId()));
                or.should(stageAnd);

                BoolQueryBuilder twoOr = QueryBuilders.boolQuery();
                twoOr.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.operationStage, 0));
                BoolQueryBuilder threeOr = QueryBuilders.boolQuery();
                threeOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.pid, condition.getOrgId()));
                threeOr.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.sku, "0"));
                threeOr.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(EsBusinessStudentBigLessonXcx.Fields.sku)));
                twoOr.must(threeOr);

                or.should(twoOr);

                qb.must(or);
                log.info(or.toString());
            } else if (condition.getLevel().equals("4")) {
                BoolQueryBuilder or = QueryBuilders.boolQuery();
                or.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.u1Sku, condition.getOrgId()));
                or.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.sku, condition.getOrgId()));

                BoolQueryBuilder twoOr = QueryBuilders.boolQuery();
                twoOr.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.operationStage, 2));
                twoOr.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.u2Sku, condition.getOrgId()));
                or.should(twoOr);

                qb.must(or);
            } else if (condition.getLevel().equals("5")) {
                BoolQueryBuilder or = QueryBuilders.boolQuery();
                or.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.u1WorkRoom, condition.getOrgId()));
                or.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.workRoom, condition.getOrgId()));

                BoolQueryBuilder twoOr = QueryBuilders.boolQuery();
                twoOr.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.operationStage, 2));
                twoOr.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.u2WorkRoom, condition.getOrgId()));
                or.should(twoOr);

                qb.must(or);
            } else if (condition.getLevel().equals("6")) {
                BoolQueryBuilder or = QueryBuilders.boolQuery();
                or.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.u1Od, condition.getOrgId()));
                or.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.od, condition.getOrgId()));

                BoolQueryBuilder twoOr = QueryBuilders.boolQuery();
                twoOr.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.operationStage, 2));
                twoOr.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.u2Od, condition.getOrgId()));
                or.should(twoOr);

                qb.must(or);
            } else if (condition.getLevel().equals("7")) {
                BoolQueryBuilder or = QueryBuilders.boolQuery();
                or.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.u1Og, condition.getOrgId()));
                or.should(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.og, condition.getOrgId()));

                BoolQueryBuilder twoOr = QueryBuilders.boolQuery();
                twoOr.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.operationStage, 2));
                twoOr.must(QueryBuilders.matchQuery(EsBusinessStudentBigLessonXcx.Fields.u2Og, condition.getOrgId()));
                or.should(twoOr);

                qb.must(or);
            }
        }

//        qb.minimumShouldMatch(1);

        //排序条件
        FieldSortBuilder fsb = SortBuilders.fieldSort(EsBusinessStudentBigLessonXcx.Fields.payFinishTime).order(SortOrder.DESC);
        Pageable pageable = PageRequest.of(condition.getPageNumber() - 1, condition.getPageSize());
        SearchQuery query = new NativeSearchQueryBuilder().withQuery(qb).withSort(fsb).withPageable(pageable).build();
        return esBusinessStudentBigLessonXcxRepository.search(query);
    }

    private String[] toStringArray(List<String> sourceType) {
        String[] res = new String[sourceType.size()];
        for (int i = 0; i < sourceType.size(); i++) {
            res[i] = sourceType.get(i);
        }
        return res;
    }

    private List<KanbanDataFormatVO> summaryMiniOrder(KanbanPageCondition condition) {
        List<KanbanDataFormatVO> result;
        NativeSearchQuery query = buildMiniOrderSearch(
                condition.getClassId(),
                condition.getDateStart(),
                condition.getDateEnd()
        );

        result = elasticsearchTemplate.query(query, resp -> {
            //函数中传入SearchResponse对象，可以通过getAggregations获取聚合结果，然后解析后返回
            LongTerms terms = resp.getAggregations().get(EsBusinessStudentOrderInfo.Fields.teacherId);
            List<LongTerms.Bucket> buckets = terms.getBuckets();
            //遍历打印
            List<KanbanDataFormatVO> list = new ArrayList();
            for (LongTerms.Bucket bucket : buckets) {
                Aggregations a = bucket.getAggregations();
                KanbanDataFormatVO summary = buildMiniOrderResult(bucket, a);
                list.add(summary);
            }
            return list;
        });

        return result;
    }


    @Override
    public List<KanbanDataFormatVO> summaryDataByUser(KanbanPageCondition condition) {
        Set<Long> userIds = new HashSet<>();
        HashSet<Long> orgIds = new HashSet<>();
        orgIds.add(condition.getOrgId());
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("big order");
        List<KanbanDataFormatVO> bigLesson = summaryBigOrder(condition);
        stopWatch.stop();
        stopWatch.start("mini order");
        List<KanbanDataFormatVO> miniOrder = summaryMiniOrder(condition);
        stopWatch.stop();
        stopWatch.start("get by dept");
        if (!CollectionUtils.isEmpty(orgIds)) {
            userIds = mnsService.getUsersByDept(condition.getLoginUserToken(), orgIds).stream().map(UserVO::getId).collect(Collectors.toSet());
        }
        stopWatch.stop();

        List<Long> finalUserIds = userIds.stream().sorted().collect(Collectors.toList());

        stopWatch.start("data mix");
        bigLesson = bigLesson.stream().filter(kan -> {
            BusinessTeacherInfo teacher = businessTeacherInfoService.findByTeacherId(kan.getTeacherId());
            //合并数据，求和
            kan.mergerData();
            if (Objects.isNull(teacher)) {
                kan.setTeacherName("");
                kan.setGroupId(0L);
                kan.setSkuId(0L);
                kan.setStudioId(0L);
                kan.setDeptId(0L);
                return true;
            }

            kan.setSkuId(teacher.getSkuId());
            kan.setStudioId(teacher.getWorkRoomId());
            kan.setStudioName(teacher.getWorkRoomName());
            kan.setGroupId(teacher.getGroupId());
            kan.setGroupName(teacher.getGroupName());
            kan.setDeptId(teacher.getDeptId());
            kan.setTeacherName(teacher.getTeacherName());


            if (finalUserIds.contains(teacher.getTeacherId())) {
                return true;
            }
            return false;
        }).collect(Collectors.toList());

        miniOrder = miniOrder.stream().filter(kan -> {
            BusinessTeacherInfo teacher = businessTeacherInfoService.findByTeacherId(kan.getTeacherId());
            if (Objects.isNull(teacher)) {
                return false;
            }
            kan.setSkuId(teacher.getSkuId());
            kan.setStudioId(teacher.getWorkRoomId());
            kan.setStudioName(teacher.getWorkRoomName());
            kan.setGroupId(teacher.getGroupId());
            kan.setGroupName(teacher.getGroupName());
            kan.setDeptId(teacher.getDeptId());
            kan.setTeacherName(teacher.getTeacherName());
            if (finalUserIds.contains(teacher.getTeacherId())) {
                return true;
            }
            return false;
        }).collect(Collectors.toList());

        List<Long> teacherIdList = new ArrayList<>();
        List<KanbanDataFormatVO> finalBigLesson = bigLesson;
        miniOrder.forEach(mini -> {
            KanbanDataFormatVO bigOrder = finalBigLesson.stream().filter(big -> big.getTeacherId().equals(mini.getTeacherId())).findFirst().orElse(null);
            if (Objects.nonNull(bigOrder)) {
                mini.extractBigOrder(bigOrder);
                teacherIdList.add(bigOrder.getTeacherId());
            }
        });


        List<KanbanDataFormatVO> collect = bigLesson.stream().filter(big -> !teacherIdList.contains(big.getTeacherId())).collect(Collectors.toList());
        miniOrder.addAll(collect);
        stopWatch.stop();
        log.info("{}", stopWatch.prettyPrint());
        return miniOrder;
    }


    public List<KanbanDataFormatVO> summaryBigOrder(KanbanPageCondition condition) {
        List<KanbanDataFormatVO> result;
        NativeSearchQuery query = buildGroupSearch(
                condition.getClassId(),
                condition.getDateStart(),
                condition.getDateEnd()
        );

        result = elasticsearchTemplate.query(query, resp -> {
            //函数中传入SearchResponse对象，可以通过getAggregations获取聚合结果，然后解析后返回
            LongTerms terms = resp.getAggregations().get(EsBusinessStudentBigLessonXcx.Fields.teacherId);
            List<LongTerms.Bucket> buckets = terms.getBuckets();
            //遍历打印
            List<KanbanDataFormatVO> list = new ArrayList();
            for (LongTerms.Bucket bucket : buckets) {
                Aggregations a = bucket.getAggregations();
                KanbanDataFormatVO summary = buildResult(bucket, a);
                list.add(summary);
            }
            return list;
        });
        return result;
    }

    private NativeSearchQuery buildMiniOrderSearch(Long lessonId, String startTime, String endTime) {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        //构建分组
        String term = EsBusinessStudentOrderInfo.Fields.teacherId;
        TermsAggregationBuilder aggBuilder = AggregationBuilders
                .terms(term).field(term)
                .subAggregation(count(KanbanDataFormatVO.Fields.orderCount).field(EsBusinessStudentOrderInfo.Fields.teacherId))
                .subAggregation(sum(KanbanDataFormatVO.Fields.addWechatGroupStateCount).field(EsBusinessStudentOrderInfo.Fields.addWechatGroupState))
                .subAggregation(sum(KanbanDataFormatVO.Fields.admissionTestStateCount).field(EsBusinessStudentOrderInfo.Fields.testCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.attnAttnCount).field(EsBusinessStudentOrderInfo.Fields.attnCountExp))
                .subAggregation(sum(KanbanDataFormatVO.Fields.attnAttnLiveCount).field(EsBusinessStudentOrderInfo.Fields.attnLiveCountExp))
                .subAggregation(sum(KanbanDataFormatVO.Fields.attnAttnVodCount).field(EsBusinessStudentOrderInfo.Fields.attnVodCountExp))
                .subAggregation(sum(KanbanDataFormatVO.Fields.attnFinishCount).field(EsBusinessStudentOrderInfo.Fields.finishCountExp))
                .subAggregation(sum(KanbanDataFormatVO.Fields.attnFinishLiveCount).field(EsBusinessStudentOrderInfo.Fields.finishLiveCountExp))
                .subAggregation(sum(KanbanDataFormatVO.Fields.attnFullDuration).field(EsBusinessStudentOrderInfo.Fields.durationCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.attnTotalDuration).field(EsBusinessStudentOrderInfo.Fields.classCourseDuration))
                .subAggregation(sum(KanbanDataFormatVO.Fields.followPublicCount).field(EsBusinessStudentOrderInfo.Fields.followPublic))
                .subAggregation(sum(KanbanDataFormatVO.Fields.getCouponCount).field(EsBusinessStudentOrderInfo.Fields.getCoupon))
                .subAggregation(sum(KanbanDataFormatVO.Fields.statesCount).field(EsBusinessStudentOrderInfo.Fields.wechatCountByStates))
                .subAggregation(sum(KanbanDataFormatVO.Fields.unPayZeroStateCount).field(EsBusinessStudentOrderInfo.Fields.unPayZeroState))
                .subAggregation(sum(KanbanDataFormatVO.Fields.attnFullLiveDuration).field(EsBusinessStudentOrderInfo.Fields.durationLiveCount))
                .size(Integer.MAX_VALUE);
        builder.addAggregation(aggBuilder);

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //加入时间范围搜索
        if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
            Date s = DateUtil.parse(startTime, DatePattern.NORM_DATETIME_MINUTE_FORMAT);
            Date e = DateUtil.parse(endTime, DatePattern.NORM_DATETIME_MINUTE_FORMAT);
            RangeQueryBuilder rangequerybuilder = QueryBuilders
                    .rangeQuery(EsBusinessStudentOrderInfo.Fields.orderPayTime)
                    .from(s.getTime())
                    .to(e.getTime());

            boolQueryBuilder.must(rangequerybuilder);

        }
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(EsBusinessStudentOrderInfo.Fields.businessType, 0);
        boolQueryBuilder.must(matchQueryBuilder);

        builder.withQuery(boolQueryBuilder);
        builder.withIndices(EsBusinessStudentOrderInfo.index);
        return builder.build();

    }

    /**
     * 按组搜索，构建搜索条件
     */
    private NativeSearchQuery buildGroupSearch(Long lessonId, String startTime, String endTime) {

        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        //构建分组
        String term = EsBusinessStudentBigLessonXcx.Fields.teacherId;
        TermsAggregationBuilder aggBuilder = AggregationBuilders
                .terms(term).field(term)
                .subAggregation(sum(KanbanDataFormatVO.Fields.xcxFee).field(EsBusinessStudentBigLessonXcx.Fields.xcxFee))
                .subAggregation(count(KanbanDataFormatVO.Fields.xcxCount).field(EsBusinessStudentBigLessonXcx.Fields.xcxCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.xcxRefundFee).field(EsBusinessStudentBigLessonXcx.Fields.xcxRefundFee))
                .subAggregation(sum(KanbanDataFormatVO.Fields.youzanFee).field(EsBusinessStudentBigLessonXcx.Fields.youzanFee))
                .subAggregation(sum(KanbanDataFormatVO.Fields.secYouzanFee).field(EsBusinessStudentBigLessonXcx.Fields.secYouzanFee))
                .subAggregation(sum(KanbanDataFormatVO.Fields.youzanCount).field(EsBusinessStudentBigLessonXcx.Fields.youzanCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.youzanRefundFee).field(EsBusinessStudentBigLessonXcx.Fields.youzanRefundFee))
                .subAggregation(sum(KanbanDataFormatVO.Fields.bigLessonRefundFee).field(EsBusinessStudentBigLessonXcx.Fields.bigLessonRefundFee))
                .subAggregation(sum(KanbanDataFormatVO.Fields.bigLessonPrice).field(EsBusinessStudentBigLessonXcx.Fields.bigLessonPrice))
                .subAggregation(count(KanbanDataFormatVO.Fields.bigLessonCount).field(EsBusinessStudentBigLessonXcx.Fields.bigLessonCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.bigLessonPriceTotal).field(EsBusinessStudentBigLessonXcx.Fields.bigLessonPriceTotal))
                .subAggregation(count(KanbanDataFormatVO.Fields.bigLessonDepositCount).field(EsBusinessStudentBigLessonXcx.Fields.bigLessonDepositCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.unRefBigLessonPrice).field(EsBusinessStudentBigLessonXcx.Fields.unRefBigLessonPrice))
                .subAggregation(sum(KanbanDataFormatVO.Fields.unRefBigLessonDepositCount).field(EsBusinessStudentBigLessonXcx.Fields.unRefBigLessonDepositCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.unRefBigLessonPriceTotal).field(EsBusinessStudentBigLessonXcx.Fields.unRefBigLessonPriceTotal))
                .subAggregation(sum(KanbanDataFormatVO.Fields.unRefYouzanFee).field(EsBusinessStudentBigLessonXcx.Fields.unRefYouzanFee))
                .subAggregation(sum(KanbanDataFormatVO.Fields.unRefYouzanCount).field(EsBusinessStudentBigLessonXcx.Fields.unRefYouzanCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.unRefXcxFee).field(EsBusinessStudentBigLessonXcx.Fields.unRefXcxFee))
                .subAggregation(sum(KanbanDataFormatVO.Fields.unRefXcxCount).field(EsBusinessStudentBigLessonXcx.Fields.unRefXcxCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.unRefBigLessonCount).field(EsBusinessStudentBigLessonXcx.Fields.unRefBigLessonCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.secBigLessonCount).field(EsBusinessStudentBigLessonXcx.Fields.secBigLessonCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.secBigLessonDepositCount).field(EsBusinessStudentBigLessonXcx.Fields.secBigLessonDepositCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.secBigLessonPrice).field(EsBusinessStudentBigLessonXcx.Fields.secBigLessonPrice))
                .subAggregation(sum(KanbanDataFormatVO.Fields.secBigLessonPriceTotal).field(EsBusinessStudentBigLessonXcx.Fields.secBigLessonPriceTotal))
                .subAggregation(sum(KanbanDataFormatVO.Fields.secBigLessonRefundFee).field(EsBusinessStudentBigLessonXcx.Fields.secBigLessonRefundFee))
                .subAggregation(sum(KanbanDataFormatVO.Fields.secYouzanRefundFee).field(EsBusinessStudentBigLessonXcx.Fields.secYouzanRefundFee))
                .subAggregation(sum(KanbanDataFormatVO.Fields.secXcxCount).field(EsBusinessStudentBigLessonXcx.Fields.secXcxCount))
                .subAggregation(sum(KanbanDataFormatVO.Fields.secXcxFee).field(EsBusinessStudentBigLessonXcx.Fields.secXcxFee))
                .subAggregation(sum(KanbanDataFormatVO.Fields.secXcxRefundFee).field(EsBusinessStudentBigLessonXcx.Fields.secXcxRefundFee))
                .size(Integer.MAX_VALUE);


        builder.addAggregation(aggBuilder);

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //加入时间范围搜索
        if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
            Date s = DateUtil.parse(startTime, DatePattern.NORM_DATETIME_MINUTE_FORMAT);
            Date e = DateUtil.parse(endTime, DatePattern.NORM_DATETIME_MINUTE_FORMAT);
            RangeQueryBuilder rangequerybuilder = QueryBuilders
                    .rangeQuery(EsBusinessStudentBigLessonXcx.Fields.payFinishTime)
                    .from(s.getTime())
                    .to(e.getTime());
            boolQueryBuilder.must(rangequerybuilder);
        }

        builder.withQuery(boolQueryBuilder);
        builder.withIndices(EsBusinessStudentBigLessonXcx.index);
        return builder.build();

    }

    /**
     * 创建搜索结果
     */
    private KanbanDataFormatVO buildResult(LongTerms.Bucket bucket, Aggregations a) {

        return KanbanDataFormatVO.builder()
                .teacherId((long) Float.parseFloat(bucket.getKeyAsString()))
                .xcxFee(getFloatValue(a, KanbanDataFormatVO.Fields.xcxFee))
                .xcxCount(getIntegerValue(a, KanbanDataFormatVO.Fields.xcxCount))
                .xcxRefundFee(getFloatValue(a, KanbanDataFormatVO.Fields.xcxRefundFee))
                .youzanFee(getFloatValue(a, KanbanDataFormatVO.Fields.youzanFee))
                .secYouzanFee(getFloatValue(a, KanbanDataFormatVO.Fields.secYouzanFee))
                .youzanCount((int) getFloatValue(a, KanbanDataFormatVO.Fields.youzanCount))
                .youzanRefundFee(getFloatValue(a, KanbanDataFormatVO.Fields.youzanRefundFee))
                .bigLessonRefundFee(getFloatValue(a, KanbanDataFormatVO.Fields.bigLessonRefundFee))
                .bigLessonPrice(getFloatValue(a, KanbanDataFormatVO.Fields.bigLessonPrice))
                .bigLessonCount(getIntegerValue(a, KanbanDataFormatVO.Fields.bigLessonCount))
                .bigLessonPriceTotal(getFloatValue(a, KanbanDataFormatVO.Fields.bigLessonPriceTotal))
                .bigLessonDepositCount(getIntegerValue(a, KanbanDataFormatVO.Fields.bigLessonDepositCount))
                .unRefBigLessonCount((int) getFloatValue(a, KanbanDataFormatVO.Fields.unRefBigLessonCount))
                .unRefBigLessonPrice(getFloatValue(a, KanbanDataFormatVO.Fields.unRefBigLessonPrice))
                .unRefXcxCount((int) getFloatValue(a, KanbanDataFormatVO.Fields.unRefXcxCount))
                .unRefXcxFee(getFloatValue(a, KanbanDataFormatVO.Fields.unRefXcxFee))
                .unRefYouzanFee(getFloatValue(a, KanbanDataFormatVO.Fields.unRefYouzanFee))
                .unRefYouzanCount((int) getFloatValue(a, KanbanDataFormatVO.Fields.unRefYouzanCount))
                .unRefBigLessonPriceTotal(getFloatValue(a, KanbanDataFormatVO.Fields.unRefBigLessonPriceTotal))
                .unRefBigLessonDepositCount((int) getFloatValue(a, KanbanDataFormatVO.Fields.unRefBigLessonDepositCount))
                .secBigLessonCount((int) getFloatValue(a, KanbanDataFormatVO.Fields.secBigLessonCount))
                .secBigLessonDepositCount((int) getFloatValue(a, KanbanDataFormatVO.Fields.secBigLessonDepositCount))
                .secBigLessonPrice(getFloatValue(a, KanbanDataFormatVO.Fields.secBigLessonPrice))
                .secBigLessonPriceTotal(getFloatValue(a, KanbanDataFormatVO.Fields.secBigLessonPriceTotal))
                .secBigLessonRefundFee(getFloatValue(a, KanbanDataFormatVO.Fields.secBigLessonRefundFee))
                .secYouzanRefundFee(getFloatValue(a, KanbanDataFormatVO.Fields.secYouzanRefundFee))
                .secXcxCount((int) getFloatValue(a, KanbanDataFormatVO.Fields.secXcxCount))
                .secXcxFee(getFloatValue(a, KanbanDataFormatVO.Fields.secXcxFee))
                .secXcxRefundFee(getFloatValue(a, KanbanDataFormatVO.Fields.secXcxRefundFee))
                .build();
    }


    private KanbanDataFormatVO buildMiniOrderResult(LongTerms.Bucket bucket, Aggregations a) {
        return KanbanDataFormatVO.builder()
                .teacherId((long) Float.parseFloat(bucket.getKeyAsString()))
                .orderCount((long) getIntegerValue(a, KanbanDataFormatVO.Fields.orderCount))
                .addWechatGroupStateCount((long) getFloatValue(a, KanbanDataFormatVO.Fields.addWechatGroupStateCount))
                .admissionTestStateCount((long) getFloatValue(a, KanbanDataFormatVO.Fields.admissionTestStateCount))
                .attnAttnCount((long) getFloatValue(a, KanbanDataFormatVO.Fields.attnAttnCount))
                .attnAttnLiveCount((long) getFloatValue(a, KanbanDataFormatVO.Fields.attnAttnLiveCount))
                .attnAttnVodCount((long) getFloatValue(a, KanbanDataFormatVO.Fields.attnAttnVodCount))
                .attnFinishCount((long) getFloatValue(a, KanbanDataFormatVO.Fields.attnFinishCount))
                .attnFinishLiveCount((long) getFloatValue(a, KanbanDataFormatVO.Fields.attnFinishLiveCount))
                .followPublicCount((long) getFloatValue(a, KanbanDataFormatVO.Fields.followPublicCount))
                .getCouponCount((long) getFloatValue(a, KanbanDataFormatVO.Fields.getCouponCount))
                .statesCount((long) getFloatValue(a, KanbanDataFormatVO.Fields.statesCount))
                .unPayZeroStateCount((long) getFloatValue(a, KanbanDataFormatVO.Fields.unPayZeroStateCount))
                .attnTotalDuration((long) getFloatValue(a, KanbanDataFormatVO.Fields.attnTotalDuration))
                .attnFullDuration((long) getFloatValue(a, KanbanDataFormatVO.Fields.attnFullDuration))
                .attnFullLiveDuration((long) getFloatValue(a, KanbanDataFormatVO.Fields.attnFullLiveDuration))
                .build();
    }

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Autowired
    private EsBusinessStudentBigLessonXcxRepository esBusinessStudentBigLessonXcxRepository;
}
